using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace Sensor.UI.Utils;

/// <summary>
/// 高效异步UI更新器，避免阻塞数据处理线程
/// </summary>
public class AsyncUIUpdater : IDisposable
{
    private readonly ConcurrentQueue<string> _updateQueue = new();
    private readonly SemaphoreSlim _updateLock = new(1, 1);
    private readonly Timer _flushTimer;
    private readonly CancellationTokenSource _cancellationTokenSource = new();
    private bool _disposedValue = false;
    
    // UI更新配置
    private readonly TimeSpan _maxUpdateInterval = TimeSpan.FromMilliseconds(16); // 约60FPS
    private readonly int _maxBatchSize = 50; // 最大批处理大小
    private DateTime _lastUpdate = DateTime.MinValue;
    
    // 性能计数器
    private long _updateCount = 0;
    private long _skipCount = 0;
    
    public long UpdateCount => _updateCount;
    public long SkipCount => _skipCount;
    public int QueueCount => _updateQueue.Count;
    
    // 事件
    public event Action<string>? OnUIUpdate;
    
    public AsyncUIUpdater()
    {
        // 设置定时器，定期强制刷新UI
        _flushTimer = new Timer(ForceFlush, null, _maxUpdateInterval, _maxUpdateInterval);
    }
    
    /// <summary>
    /// 调度UI更新
    /// </summary>
    /// <param name="data">要更新的数据</param>
    public void ScheduleUpdate(string data)
    {
        if (_disposedValue || string.IsNullOrEmpty(data))
            return;
            
        // 添加到队列
        _updateQueue.Enqueue(data);
        
        // 检查是否需要立即更新
        var now = DateTime.UtcNow;
        if (now - _lastUpdate >= _maxUpdateInterval || _updateQueue.Count >= _maxBatchSize)
        {
            TriggerUpdate();
        }
    }
    
    /// <summary>
    /// 触发UI更新
    /// </summary>
    private void TriggerUpdate()
    {
        if (_updateLock.Wait(0)) // 非阻塞获取锁
        {
            try
            {
                Task.Run(ProcessUpdatesAsync, _cancellationTokenSource.Token);
            }
            finally
            {
                _updateLock.Release();
            }
        }
        else
        {
            Interlocked.Increment(ref _skipCount);
        }
    }
    
    /// <summary>
    /// 处理更新队列
    /// </summary>
    private async Task ProcessUpdatesAsync()
    {
        if (_updateQueue.IsEmpty)
            return;
            
        // 收集要更新的数据
        var updates = new List<string>();
        while (updates.Count < _maxBatchSize && _updateQueue.TryDequeue(out string? update))
        {
            updates.Add(update);
        }
        
        if (updates.Count == 0)
            return;
            
        // 合并数据
        var combinedData = string.Join(Environment.NewLine, updates);
        
        // 使用BeginInvoke进行异步UI更新
        if (Application.Current?.Dispatcher != null)
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
            {
                try
                {
                    OnUIUpdate?.Invoke(combinedData);
                    Interlocked.Add(ref _updateCount, updates.Count);
                    _lastUpdate = DateTime.UtcNow;
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"UI更新错误: {ex.Message}");
                }
            }));
        }
    }
    
    /// <summary>
    /// 定时器回调，强制刷新UI
    /// </summary>
    private void ForceFlush(object? state)
    {
        if (!_updateQueue.IsEmpty)
        {
            TriggerUpdate();
        }
    }
    
    /// <summary>
    /// 立即刷新所有待更新的数据
    /// </summary>
    public void Flush()
    {
        _lastUpdate = DateTime.MinValue; // 强制更新
        TriggerUpdate();
    }
    
    #region IDisposable实现
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _cancellationTokenSource.Cancel();
                _flushTimer?.Dispose();
                _updateLock.Dispose();
                
                // 清空队列
                while (_updateQueue.TryDequeue(out _)) { }
            }
            _disposedValue = true;
        }
    }
    
    public void Dispose()
    {
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
    #endregion
}